/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import cn.hutool.core.collection.CollectionUtil;
import com.anwen.mongo.aggregate.AggregateWrapper;
import com.anwen.mongo.aggregate.pipeline.Accumulators;
import com.anwen.mongo.conditions.query.LambdaQueryChainWrapper;
import com.anwen.mongo.mapper.BaseMapper;
import com.anwen.mongo.mapping.TypeReference;
import com.anwen.mongo.model.PageResult;
import com.anwen.mongo.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.core.exception.ServiceException;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.excel.utils.ExcelUtil;
import com.comac.ins.common.json.utils.JsonUtils;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.MongoDataConstant;
import com.comac.ins.isfd.constant.enums.IsfdImportMethodEnum;
import com.comac.ins.isfd.constant.enums.IsfdMetadataTableNameEnum;
import com.comac.ins.isfd.constant.enums.MetaDataBusinessScenarioNoEnum;
import com.comac.ins.isfd.constant.enums.MetaDataStorageTypeEnum;
import com.comac.ins.isfd.domain.FastenerAllowableValueCodeGeneration;
import com.comac.ins.isfd.domain.FastenerObject;
import com.comac.ins.isfd.domain.IsfdDatabaseModelConfig;
import com.comac.ins.isfd.domain.IsfdMetadata;
import com.comac.ins.isfd.domain.bo.FastenerInfoBo;
import com.comac.ins.isfd.domain.bo.FastenerModelBo;
import com.comac.ins.isfd.domain.bo.FastenerOriginalInfoBo;
import com.comac.ins.isfd.domain.bo.query.FastenerOriginalInfoQueryBo;
import com.comac.ins.isfd.domain.bo.query.FastenerQueryBo;
import com.comac.ins.isfd.domain.bo.query.FasteneraAllowableValueQueryBo;
import com.comac.ins.isfd.domain.bo.query.FastenerInfoAllowableValueQueryBo;
import com.comac.ins.isfd.domain.bo.query.FastenerModelAllowableValueQueryBo;
import com.comac.ins.isfd.domain.bo.query.ResultSplitAndSaveExcelTablesBo;
import com.comac.ins.isfd.domain.vo.FastenerCountObjectVo;
import com.comac.ins.isfd.domain.vo.FastenerImportObjectVo;
import com.comac.ins.isfd.domain.vo.FastenerInfoAllowableVo;
import com.comac.ins.isfd.domain.vo.FastenerInfoVo;
import com.comac.ins.isfd.domain.vo.FastenerModelTreeVo;
import com.comac.ins.isfd.domain.vo.IsfdFastenerCountObjectVo;
import com.comac.ins.isfd.domain.vo.IsfdTreeNodeVo;
import com.comac.ins.isfd.mapper.IsfdDatabaseModelConfigMapper;
import com.comac.ins.isfd.mapper.IsfdFastenerAllowableValueCodeGenerationMapper;
import com.comac.ins.isfd.mapper.IsfdMetadataMapper;
import com.comac.ins.isfd.service.IFastenerInfoService;
import com.comac.ins.isfd.service.IFastenerModelService;
import com.comac.ins.isfd.service.IFastenerOriginalInfoService;
import com.comac.ins.isfd.service.IFastenerService;
import com.comac.ins.isfd.service.IIsfdDatabaseDataManagementService;
import com.comac.ins.isfd.service.IIsfdMetadataImportService;
import com.comac.ins.isfd.strategy.FastenerCodeGenerationStrategy;
import com.comac.ins.isfd.strategy.FastenerCodeGenerationStrategyFactory;
import com.comac.ins.isfd.util.FastenerSplitExcelUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import static com.comac.ins.isfd.constant.IsfdMeshOp2Constants.UPLOAD_FASTENER_EXCEL;

/**
 * 紧固件service实现类
 *
 * @author hxloongs
 * @date 2024-7-3
 */
@Slf4j
@Service
public class IFastenerServiceImpl extends ServiceImpl<FastenerObject> implements IFastenerService, MongoDataConstant, IIsfdMetadataImportService {

    @Autowired
    private IsfdMetadataMapper isfdMetadataMapper;

    @Autowired
    private IsfdFastenerAllowableValueCodeGenerationMapper isfdFastenerAllowableValueCodeGenerationMapper;

    @Autowired
    private BaseMapper baseMapper;

    @Autowired
    @Qualifier("fastenerCodeGenerationMap")
    private Map<String, FastenerCodeGenerationStrategy> fastenerCodeGenerationStrategies;

    @Autowired
    private IFastenerModelService iFastenerModelService;

    @Autowired
    private IFastenerInfoService iFastenerInfoService;

    @Autowired
    private IFastenerOriginalInfoService iFastenerOriginalInfoService;
    @Autowired
    private IIsfdDatabaseDataManagementService isfdDatabaseDataManagementService;
    @Autowired
    private IsfdDatabaseModelConfigMapper isfdDatabaseModelConfigMapper;

    @Override
    public List<FastenerCountObjectVo> listCount() {
        // 1.查询元数据是否存在数据
        LambdaQueryWrapper<IsfdMetadata> lqw = Wrappers.lambdaQuery();
        lqw.eq(IsfdMetadata::getBusinessScenarioNo, MetaDataBusinessScenarioNoEnum.CAE.getValue());
        lqw.eq(IsfdMetadata::getTableName, FASTENER_EXPORT_DATA);
        IsfdMetadata isfdMetadata = isfdMetadataMapper.selectOne(lqw);

        // 2.根据元数据中的storage type进行对应的db查询统计
        List<FastenerCountObjectVo> result = new ArrayList<>();
        if (isfdMetadata != null && MetaDataStorageTypeEnum.MONGODB.getValue().equals(isfdMetadata.getStorageType())) {
            MongoCollection mongoCollection = baseMapper.getMongoPlusClient().getCollection(DB_NAME, isfdMetadata.getTableName());
            List<Document> pipeline = Arrays.asList(
                new Document($_GROUP, new Document(ID, $ + TYPE).append(COUNT, new Document($_SUM, INCLUDE)))
            );
            AggregateIterable<Document> aggregateIterable = mongoCollection.aggregate(pipeline);
            aggregateIterable.forEach(document -> {
                FastenerCountObjectVo fastenerCountObjectVo = new FastenerCountObjectVo();
                fastenerCountObjectVo.setType(document.getString(ID));
                fastenerCountObjectVo.setCount(document.getLong(COUNT));
                result.add(fastenerCountObjectVo);
            });
        }
        return result;
    }

    @Override
    public List<IsfdFastenerCountObjectVo> listCountByListByField(String field) {
        AggregateWrapper groupAggregateWrapper = new AggregateWrapper();
        groupAggregateWrapper.group("$" + field,
            Accumulators.sum(field, 1));

        List<Map<String, Object>> maps = baseMapper.aggregateList(DB_NAME, FASTENER_EXPORT_DATA, groupAggregateWrapper, new TypeReference<Map<String, Object>>() {
        });
        return maps.stream()
            .map(item -> new IsfdFastenerCountObjectVo(null, (String) item.get("_id"), Long.valueOf(item.get(field).toString())))
            .toList();
    }

    @Override
    public IsfdTreeNodeVo listTree() {
        // 初始化最外层root节点
        IsfdTreeNodeVo<IsfdTreeNodeVo> rootNode = new IsfdTreeNodeVo("-1", "root", "root", null);

        // 查询元数据是否存在数据
        LambdaQueryWrapper<IsfdMetadata> lqw = Wrappers.lambdaQuery();
        lqw.eq(IsfdMetadata::getBusinessScenarioNo, MetaDataBusinessScenarioNoEnum.CAE.getValue());
        lqw.eq(IsfdMetadata::getTableName, FASTENER_EXPORT_DATA);
        IsfdMetadata isfdMetadata = isfdMetadataMapper.selectOne(lqw);
        if (isfdMetadata == null) {
            return rootNode;
        }

        // 封装子节点
        if (MetaDataStorageTypeEnum.MONGODB.getValue().equals(isfdMetadata.getStorageType())) {
            rootNode.setChildren(new ArrayList<>());
            List<Map<String, Object>> result = baseMapper.list(isfdMetadata.getTableName(), new TypeReference<Map<String, Object>>() {
            });
            //根据type分组
            Map<String, List<Map<String, Object>>> groupedResults = result.stream().collect(Collectors.groupingBy(record -> record.get("type").toString()));
            AtomicInteger counter = new AtomicInteger(0);
            groupedResults.forEach((type, group) -> {
                IsfdTreeNodeVo node = new IsfdTreeNodeVo();
                node.setNodeId(String.valueOf(counter.incrementAndGet()));
                node.setNodeType(type);
                node.setNodeName(type);
                node.setChildren(group);
                rootNode.getChildren().add(node);
            });
        }
        return rootNode;
    }

    @Override
    public TableDataInfo<FastenerImportObjectVo> queryPageList(FastenerQueryBo queryBo) {
        // 构造返回列表
        List<FastenerObject> fastenerObjectList = new ArrayList<>();
        Integer pageNum = queryBo.getPageNum();
        Integer pageSize = queryBo.getPageSize();

        // 构造查询参数
        LambdaQueryChainWrapper<FastenerObject> queryChainWrapper = this.lambdaQuery();
        queryChainWrapper.in(CollectionUtil.isNotEmpty(queryBo.getMetadataManagementIds()), FastenerObject::getMetadataManagementId, queryBo.getMetadataManagementIds());

        // 进行mongodb分页查询
        PageResult<FastenerObject> page = this.page(queryChainWrapper, pageNum, pageSize);
        fastenerObjectList.addAll(page.getContentData());
        Long total = page.getTotalSize();

        // 空集直接返回
        if (CollectionUtil.isEmpty(fastenerObjectList)) {
            return TableDataInfo.build();
        }
        // 返回vos
        List<FastenerImportObjectVo> voList = MapstructUtils.convert(fastenerObjectList, FastenerImportObjectVo.class);

        return TableDataInfo.buildToPageMemoryLimit(Boolean.FALSE, voList, pageNum, pageSize, total);
    }

    @Override
    public List<String> allowableValueList(FasteneraAllowableValueQueryBo queryBo) {
        List<String> allowableValueList = new LinkedList<>();
        FastenerCodeGenerationStrategy.FastenerCodeContext fastenerCodeContext = new FastenerCodeGenerationStrategy.FastenerCodeContext();
        String fastenerGradeString = queryBo.getFastenerGrade();
        // 检查是否包含"或者、"分隔符
        List<String> fastenerGradeList = new ArrayList<>();
        if (fastenerGradeString.contains("、")) {
            // 拆分并添加到新集合
            String[] parts = fastenerGradeString.split("、");
            fastenerGradeList.addAll(Arrays.asList(parts));
        } else if (fastenerGradeString.contains(",")) {
            // 拆分并添加到新集合
            String[] parts = fastenerGradeString.split(",");
            fastenerGradeList.addAll(Arrays.asList(parts));
        } else {
            // 不包含分隔符则直接添加
            fastenerGradeList.add(fastenerGradeString);
        }
        for (String fastenerGrade : fastenerGradeList) {
            if (StringUtils.isNotBlank(fastenerGrade)) {
                String diameterCodeStr = queryBo.getDiameterCode();
                // 处理直径代码转换
                Integer diameterCode = 0;
                try {
                    if (diameterCodeStr != null && !diameterCodeStr.trim().isEmpty()) {
                        // 先转换为Double处理可能的小数格式
                        Double diameterDouble = Double.parseDouble(diameterCodeStr.trim());
                        // 取整数部分
                        diameterCode = diameterDouble.intValue();
                    }
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Invalid diameter code: " + diameterCodeStr, e);
                }

                fastenerCodeContext.setFastenerGrade(fastenerGrade);
                fastenerCodeContext.setDiameterCode(diameterCode);
                fastenerCodeContext.setDashNumber(queryBo.getDashNumber());
                // 根据fastenerGrade获取surfaceTreatments和是否补0
                // 构造生成器规则查询参数
                LambdaQueryWrapper<FastenerAllowableValueCodeGeneration> lqw = Wrappers.lambdaQuery();
                lqw.eq(FastenerAllowableValueCodeGeneration::getFastenerGrade, fastenerGrade);
                // diameterCode如果有值判断查询的diameterCode是否在里面
                if (Objects.nonNull(diameterCode)) {
                    lqw.apply("FIND_IN_SET({0}, diameter_code)", diameterCode.toString());
                }
                FastenerAllowableValueCodeGeneration fastenerAllowableValueCodeGeneration = isfdFastenerAllowableValueCodeGenerationMapper.selectOne(lqw);
                if (!Objects.nonNull(fastenerAllowableValueCodeGeneration)) {
                    throw new BaseException("该牌号规则未找到！");
                }
                String generationStrategy = fastenerAllowableValueCodeGeneration.getGenerationStrategy();
                fastenerCodeContext.setSurfaceTreatment(fastenerAllowableValueCodeGeneration.getSurfaceTreatment());
                fastenerCodeContext.setPadZeroForSingleDigit(fastenerAllowableValueCodeGeneration.isPadZeroForSingleDigit());
                fastenerCodeContext.setAddDashNumber(fastenerAllowableValueCodeGeneration.isAddDashNumber());
                FastenerCodeGenerationStrategy strategy = fastenerCodeGenerationStrategies.getOrDefault(generationStrategy, FastenerCodeGenerationStrategyFactory.EMPTY_STRATEGY);
                List<String> allowableValueListByFastenerGrade = strategy.generateCodes(fastenerCodeContext);
                allowableValueList.addAll(allowableValueListByFastenerGrade);
            }
        }
        return allowableValueList;
    }

    @Override
    public List<ResultSplitAndSaveExcelTablesBo> allowableValueUploadExcel(MultipartFile file) {
        try {
            List<ResultSplitAndSaveExcelTablesBo> resultSplitAndSaveExcelTablesBoList = FastenerSplitExcelUtils.splitAndSaveExcelTables(file.getInputStream(), file.getOriginalFilename(), UPLOAD_FASTENER_EXCEL);
            // 保存在表里
            for (ResultSplitAndSaveExcelTablesBo resultSplitAndSaveExcelTablesBo : resultSplitAndSaveExcelTablesBoList) {
                FastenerModelBo fastenerModelBo = resultSplitAndSaveExcelTablesBo.getFastenerModelBo();
                List<FastenerInfoBo> fastenerInfoList = fastenerModelBo.getFastenerInfoList();
                iFastenerInfoService.saveBatch(fastenerInfoList);
                List<String> fastenerInfoIdList = fastenerInfoList.stream()
                    .map(FastenerInfoBo::get_id)
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.toList());
                fastenerModelBo.setFastenerInfo(fastenerInfoIdList);
                fastenerModelBo.setUrl(resultSplitAndSaveExcelTablesBo.getResultExcel());
                iFastenerModelService.save(fastenerModelBo);
            }
            return resultSplitAndSaveExcelTablesBoList;
        } catch (IOException e) {
            throw new ServiceException("文件上传失败" + e.getMessage());
        }
    }

    @Override
    public Long originalInfoUploadExcel(File file, LoginUser loginUser) {
        long successCount = 0L;
        try (InputStream is = new FileInputStream(file)) {
            // 只处理 .xlsx 文件
            List<FastenerOriginalInfoBo> importVoList = ExcelUtil.importExcel(is, FastenerOriginalInfoBo.class);
            try {
//                    iFastenerOriginalInfoService.save(importVoList.get(i));
                List<Map<String, Object>> entityListJson = JsonUtils.parseJsonStrToListMap(JsonUtils.toJsonString(importVoList));
                IsfdDatabaseModelConfig modelConfig = isfdDatabaseModelConfigMapper.selectModelByModelName("fastener_original_info");
                String tableName = modelConfig.getTableName();
                if (!StringUtils.isNotBlank(tableName)) {
                    throw new BaseException("紧固件原始表未找到！");
                }
                isfdDatabaseDataManagementService.insertOrUpdateDataList(tableName, entityListJson, IsfdImportMethodEnum.DIRECTLY, null, false);
                successCount++;
            } catch (Exception e) {
                log.error("紧固件原始数据导入失败", e);
            }
        } catch (Exception e) {
            log.error("紧固件原始导入失败", e);
            throw new BaseException("紧固件原始导入失败：" + e.getMessage());
        }
        return successCount;
    }

    @Override
    public void exportOriginalInfo(FastenerOriginalInfoQueryBo queryBo, HttpServletResponse response) {
        // 设置导出全部数据
        queryBo.setPageNum(1);
        queryBo.setPageSize(Integer.MAX_VALUE);
        List<FastenerOriginalInfoBo> fastenerOriginalInfoList = getFastenerOriginalInfoList(queryBo);

        // 构建表头
        List<String> headerList = Arrays.asList(
            "类型Type", "名称Name", "材料Material", "标准Standard", "采购/技术规范",
            "索引的材料规范", "材料规范对应的G/1000（ksi）", "说明Description",
            "直径D", "长度L", "A", "H", "E", "尺寸参考文献",
            "拉伸许用载荷TF", "剪切许用载荷SF", "是否双剪", "载荷参考文献",
            "拉伸许用应力TS", "剪切许用应力SS", "应力参考文献",
            "材料修正系数Kdc", "材料修正系数参考文献",
            "钉间失稳系数C", "钉间失稳参考文献", "适用机型", "自带螺母直径", "单位"
        );

        // 构造数据列表
        List<Map<String, Object>> dataList = fastenerOriginalInfoList.stream().map(info -> {
            Map<String, Object> row = new LinkedHashMap<>();
            row.put("类型Type", info.getTypeSource());
            row.put("名称Name", info.getNameSource());
            row.put("材料Material", info.getMaterialSource());
            row.put("标准Standard", info.getStandardSource());
            row.put("采购/技术规范", info.getProcurementTechnicalSpecifications());
            row.put("索引的材料规范", info.getTechnicalSpecifications());
            row.put("材料规范对应的G/1000（ksi）", info.getGMpaSource());
            row.put("说明Description", info.getDescriptionSource());
            row.put("直径D", info.getDSource());
            row.put("长度L", info.getLSource());
            row.put("A", info.getASource());
            row.put("H", info.getHSource());
            row.put("E", info.getESource());
            row.put("尺寸参考文献", info.getGeoRefSource());
            row.put("拉伸许用载荷TF", info.getTensileForceSource());
            row.put("剪切许用载荷SF", info.getShearForceSource());
            row.put("是否双剪", info.getIsDoubleSource());
            row.put("载荷参考文献", info.getForRefSource());
            row.put("拉伸许用应力TS", info.getTensileStressSource());
            row.put("剪切许用应力SS", info.getShearStressSource());
            row.put("应力参考文献", info.getStsRefSource());
            row.put("材料修正系数Kdc", info.getKdcSource());
            row.put("材料修正系数参考文献", info.getKdcRefSource());
            row.put("钉间失稳系数C", info.getConnectionFactorSource());
            row.put("钉间失稳参考文献", info.getConRefSource());
            row.put("适用机型", info.getPlaneTypeSource());
            row.put("自带螺母直径", info.getSelfContainedNutDiameter());
            row.put("单位", info.getUnit());
            return row;
        }).collect(Collectors.toList());

        // 导出Excel
        ExcelUtil.exportExcelReBuildHeader("【紧固件库原始信息】", headerList, dataList, response);
    }

    @Override
    public void exportTemplate(HttpServletResponse response) {
        // 构建表头
        List<String> headerList = Arrays.asList(
            "类型Type", "名称Name", "材料Material", "标准Standard", "采购/技术规范",
            "索引的材料规范", "材料规范对应的G/1000（ksi）", "说明Description",
            "直径D", "长度L", "A", "H", "E", "尺寸参考文献",
            "拉伸许用载荷TF", "剪切许用载荷SF", "是否双剪", "载荷参考文献",
            "拉伸许用应力TS", "剪切许用应力SS", "应力参考文献",
            "材料修正系数Kdc", "材料修正系数参考文献",
            "钉间失稳系数C", "钉间失稳参考文献", "适用机型", "自带螺母直径", "单位"
        );

        // 导出空模板
        ExcelUtil.exportExcelReBuildHeader("【紧固件库原始】模板", headerList, Collections.emptyList(), response);
    }

    @Override
    public List<IsfdTreeNodeVo<IsfdTreeNodeVo<FastenerModelTreeVo>>> getFastenerModelTreeList(FastenerModelAllowableValueQueryBo queryBo) {
        List<FastenerModelBo> fastenerModelBoList = iFastenerModelService.queryPageList(queryBo);

        Map<String, Map<String, List<FastenerModelTreeVo>>> resultMap = new LinkedHashMap<>();

        for (FastenerModelBo bo : fastenerModelBoList) {
            String fastenerGrade = bo.getFastenerGrade();
            String plateName = bo.getPlateName();

            if (StringUtils.isNotBlank(fastenerGrade) && StringUtils.isNotBlank(plateName)) {
                // 一级：fastenerGrade 分组
                Map<String, List<FastenerModelTreeVo>> plateMap = resultMap.computeIfAbsent(fastenerGrade, k -> new LinkedHashMap<>());

                // 二级：plateName 分组
                List<FastenerModelTreeVo> voList = plateMap.computeIfAbsent(plateName, p -> new ArrayList<>());

                FastenerModelTreeVo vo = new FastenerModelTreeVo();
                vo.set_id(bo.get_id());
                vo.setFastenerGrade(fastenerGrade);
                vo.setPlateName(plateName);
                vo.setSheetName(fastenerGrade + "," + plateName);
                vo.setNodeName(bo.getDataType());
                voList.add(vo);
            }
        }

        // 转换为树形结构
        List<IsfdTreeNodeVo<IsfdTreeNodeVo<FastenerModelTreeVo>>> rootNodes = new ArrayList<>();

        for (Map.Entry<String, Map<String, List<FastenerModelTreeVo>>> gradeEntry : resultMap.entrySet()) {
            String fastenerGrade = gradeEntry.getKey();
            Map<String, List<FastenerModelTreeVo>> plateMap = gradeEntry.getValue();

            // 创建等级节点
            IsfdTreeNodeVo<IsfdTreeNodeVo<FastenerModelTreeVo>> gradeNode = new IsfdTreeNodeVo<>();
            gradeNode.setNodeId(fastenerGrade);
            gradeNode.setNodeType("fastener_grade");
            gradeNode.setNodeName(fastenerGrade);
            gradeNode.setChildren(new ArrayList<>());

            for (Map.Entry<String, List<FastenerModelTreeVo>> plateEntry : plateMap.entrySet()) {
                String plateName = plateEntry.getKey();
                List<FastenerModelTreeVo> modelList = plateEntry.getValue();

                // 创建板材节点
                IsfdTreeNodeVo<FastenerModelTreeVo> plateNode = new IsfdTreeNodeVo<>();
                plateNode.setNodeId(fastenerGrade + plateName);
                plateNode.setNodeType("fastener_plate");
                plateNode.setNodeName(plateName);
                plateNode.setChildren(modelList);

                gradeNode.getChildren().add(plateNode);
            }

            rootNodes.add(gradeNode);
        }

        return rootNodes;
    }

    @Override
    public List<FastenerInfoVo> getFastenerModelAllowableValueList(FastenerInfoAllowableValueQueryBo queryBo) {
        String fasteneraModelId = queryBo.getFasteneraModelId();
        if (!StringUtils.isNotBlank(fasteneraModelId)) {
            throw new BaseException("id不能为空！");
        }
        List<FastenerInfoBo> fastenerInfoBoList = iFastenerInfoService.queryPageList(queryBo);
        Map<String, List<FastenerInfoBo>> fastenerMap = new LinkedHashMap<>();
        for (FastenerInfoBo fastener : fastenerInfoBoList) {
            String diameterCode = fastener.getDiameterCode();
            fastenerMap.computeIfAbsent(diameterCode, k -> new ArrayList<>())
                .add(fastener);
        }
        List<FastenerInfoVo> result = new ArrayList<>();
        for (Map.Entry<String, List<FastenerInfoBo>> entry : fastenerMap.entrySet()) {
            String diameterCode = entry.getKey();
            List<FastenerInfoBo> fasteners = entry.getValue();

            // 创建紧固件信息对象
            FastenerInfoVo fastenerInfoVo = new FastenerInfoVo();
            fastenerInfoVo.setDiameterCode(diameterCode);

            // 假设同一直径代码下的紧固件基本信息相同，取第一个元素
            if (CollectionUtil.isNotEmpty(fasteners)) {
                FastenerInfoBo firstFastener = fasteners.get(0);
                fastenerInfoVo.set_id(firstFastener.get_id());
                fastenerInfoVo.setThkDia(firstFastener.getThkDia());
                fastenerInfoVo.setShearStrength(firstFastener.getShearStrength());
                fastenerInfoVo.setThickness2shear(firstFastener.getThickness2shear());
                fastenerInfoVo.setNominalDiameter(firstFastener.getNominalDiameter());
                fastenerInfoVo.setHeadHeight(firstFastener.getHeadHeight());
            }

            // 收集该直径代码下的所有允许值信息
            List<FastenerInfoAllowableVo> allowableVoList = fasteners.stream()
                .map(fastener -> {
                    FastenerInfoAllowableVo allowableVo = new FastenerInfoAllowableVo();
                    allowableVo.set_id(fastener.get_id());
                    allowableVo.setThicknessMM(fastener.getThicknessMM());
                    allowableVo.setThicknessInches(fastener.getThicknessInches());
                    allowableVo.setAllowableValue(fastener.getAllowableValue());
                    return allowableVo;
                })
                .collect(Collectors.toList());

            fastenerInfoVo.setFastenerInfoAllowableVoList(allowableVoList);
            result.add(fastenerInfoVo);
        }
        return result;
    }

    @Override
    public List<FastenerOriginalInfoBo> getFastenerOriginalInfoList(FastenerOriginalInfoQueryBo queryBo) {
        List<FastenerOriginalInfoBo> fastenerInfoBoList = iFastenerOriginalInfoService.queryPageList(queryBo);
        return fastenerInfoBoList;
    }


    @Override
    public String selectByTableName() {
        return IsfdMetadataTableNameEnum.FASTENER_EXPORTDATA.getValue();
    }

    @Override
    public Long excelImport(File excelImportFile, String metadataManagementId) {
        long successCount = 0L;
        ObjectMapper objectMapper = new ObjectMapper();
        try (InputStream is = new FileInputStream(excelImportFile)) {
            String fileName = excelImportFile.getName();
            String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
            List<FastenerImportObjectVo> targetVos = new ArrayList<>();
            if (extension.equals("json")) {
                targetVos = objectMapper.readValue(is, new com.fasterxml.jackson.core.type.TypeReference<>() {
                });
            } else if (extension.equals("xlsx")) {
                targetVos = ExcelUtil.importExcel(is, FastenerImportObjectVo.class);
            } else {
                throw new BaseException("文件类型不支持：" + extension);
            }
            // 获取紧固件库
            MongoCollection<Document> mongoCollection = baseMapper.getMongoPlusClient().getCollection(DB_NAME, FASTENER_EXPORT_DATA);
            for (FastenerImportObjectVo vo : targetVos) {
                try {
                    vo.setMetadataManagementId(metadataManagementId);
                    replaceNullsWithEmptyStrings(vo);
                    // 将vo转换成doc, 插入紧固件库
                    Document document = convertVoToDocument(vo);
                    mongoCollection.insertOne(document);
                    successCount++;
                } catch (Exception e) {
                    log.error("紧固件数据导入失败", e);
                }
            }

        } catch (Exception e) {
            log.error("sheet文件转换为实体类失败", e);
            throw new BaseException("sheet文件转换为实体类失败");
        }

        return successCount;
    }

    /**
     * 将VO对象中的null值替换为空字符串。
     *
     * @param vo 要处理的对象。
     * @throws IllegalAccessException 如果不能访问字段。
     */
    public static void replaceNullsWithEmptyStrings(Object vo) throws IllegalAccessException {
        Class<?> clazz = vo.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true); // 设置为可访问私有变量
            if (field.get(vo) == null) {
                field.set(vo, "");
            }
        }
    }

    private Document convertVoToDocument(FastenerImportObjectVo vo) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            Map<String, Object> map = mapper.convertValue(vo, Map.class);
            return new Document(map);
        } catch (Exception e) {
            log.error("实体类转换为Docuement失败", e);
            throw new BaseException("实体类转换为Docuement失败");
        }
    }
}
